package com.jiejie.controller;


import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;

import com.jiejie.config.AlipayConfig;

import com.jiejie.entity.*;
import com.jiejie.mapper.CustomerAndCouponMapper;
import com.jiejie.service.*;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author 辰广
 * @since 2022-10-05
 */
@Controller
//@RequestMapping("/flow")
public class FlowController {
    @Resource
    private IFlowService flowService;
    @Resource
    private IOrderService orderService;
    @Resource
    private IMovieService movieService;
    @Resource
    private IScheduleService scheduleService;
    @Resource
    private ICustomerAndCouponService customerAndCouponService;
    @Resource
    private ICouponService couponService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostMapping("alipay")
    @ResponseBody
    public String crateOrder(String customerId,String scheduleId,String orderAdjustedPrice,String orderSeatNum,String customerAndCouponId){
        System.out.println(">>>>>>>>>>>>>>>>>");
        System.out.println(customerAndCouponId);
        Order order=new Order();
        order.setOrderNum(UUID.randomUUID().toString().replace("-",""));
        order.setCustomerId(Integer.parseInt(customerId));
        Integer movieId=scheduleService.getById(scheduleId).getMovieId();
        order.setMovieId(movieId);
        order.setScheduleId(Integer.parseInt(scheduleId));
        order.setOrderAdjustedPrice(Double.parseDouble(orderAdjustedPrice));
        order.setOrderSeatNum(orderSeatNum);
        if (!customerAndCouponId.equals("0")){
            order.setCustomerAndCouponId(Integer.parseInt(customerAndCouponId));
            Double CouponAmount=couponService.getById(customerAndCouponService.getById(Integer.parseInt(customerAndCouponId)).getCouponId()).getCouponAmount();
            order.setCouponAmount(CouponAmount);
        }
        order.setOrderCreatetime(LocalDateTime.now());
        order.setOrderStatus(0);
        order.setOrderVersion(0);
        boolean row=orderService.save(order);
        System.out.println("保存订单:"+row);
        String name=movieService.getMovieDetailById(movieId).getMovieCname();
        return alipay(name,order.getOrderNum(),order.getOrderAdjustedPrice());
    }

    //调用支付宝的接口
    public String alipay(String name, String orderNum,  Double flowPrice) {

        /*Schedule schedule=scheduleService.getById(scheduleId);
        String day= schedule.getScheduleBeginDate().equals(LocalDate.now()) ?"今天":"明天";
        String dataOne= day+"  "+schedule.getScheduleBeginDate().getMonthValue()+"月"+schedule.getScheduleBeginDate().getDayOfMonth()+"日"+"  "+schedule.getScheduleBeginTime();
*/
        //1.初始化AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl,
                AlipayConfig.app_id,
                AlipayConfig.merchant_private_key,
                "json",
                AlipayConfig.charset,
                AlipayConfig.alipay_public_key,
                AlipayConfig.sign_type);


        //2.设置请求参数，return URL
        AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest();
        payRequest.setReturnUrl(AlipayConfig.return_url);
        payRequest.setNotifyUrl(AlipayConfig.notify_url);


        System.out.println(orderNum);

        System.out.println(flowPrice);


        //商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNum;

        //付款金额，必填
        Double total_amount = flowPrice;

        // 该笔订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m。
        String timeout_express = "1c";
        payRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"body\":\""+ "电影票" +"\","
                + "\"subject\":\"《"+ name +"》\","
                + "\"timeout_express\":\""+ timeout_express +"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");


        //3.请求支付
        String result = null;
        try {
            result = alipayClient.pageExecute(payRequest).getBody();
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }
        System.out.println("result:"+result);
        return result;
    }

    // 支付宝支付成功后，需要调用的业务处理（1.添加流水，2.修改订单）
    //同步请求
    @RequestMapping("success")
    public ModelAndView returnNotice(HttpServletRequest request, HttpServletRequest response) throws UnsupportedEncodingException {
        System.out.println("支付成功后，支付宝返回的所有的数据："+request);

        //获取支付宝GET过来反馈信息
        Map<String,String> params = new HashMap<>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for(Iterator<String> iterator = requestParams.keySet().iterator(); iterator.hasNext();){
            String name =(String) iterator.next();
            String[] values = (String[]) requestParams.get(name);

            String valueStr = "";
            for (int i=0;i<values.length;i++) {
                valueStr = (i==values.length-1)?valueStr+values[i] : valueStr+values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用
            valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }

        //调用SDK验证签名
        boolean signVerified = false;
        try {
            signVerified= AlipaySignature.rsaCheckV1(params,AlipayConfig.alipay_public_key,AlipayConfig.charset,AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("pages/alipaySuccess");
        if (signVerified){
            //在支付宝结果中获得参数信息
            //商户订单号
            String orderNum= new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
            //支付宝交易号
            String seller_id= new String(request.getParameter("seller_id").getBytes("ISO-8859-1"),"UTF-8");

             //1.添加流水，2.修改订单,3.解锁座位
            sendDB(orderNum);
            Order order= orderService.getOrderByOrderNum(orderNum);
            /* Integer row=orderService.updateOrder(order);
            String[] seats= order.getOrderSeatNum().split(",");
            System.out.println("==============="+order.getOrderSeatNum());
            System.out.println("==============="+ Arrays.toString(seats));
            for (String s:seats) {
                redisTemplate.delete("seat_"+order.getScheduleId()+"_"+s);
            }*/

            Integer movieId = order.getMovieId();
            modelAndView.addObject("movieId",movieId);
            modelAndView.addObject("result","支付成功");
            return modelAndView;

            /*modelAndView.addObject("out_trade_no", out_trade_no);
            modelAndView.addObject("trade_no", trade_no);
            modelAndView.addObject("total_amount", total_amount);*/
        }else{
            modelAndView.addObject("result","支付失败");
            return modelAndView;
        }
    }
    public void sendDB(String orderNum){
        rabbitTemplate.convertAndSend("myDirectExchange", "key1", orderNum);
    }


    @Transactional
    @RabbitHandler
    @RabbitListener(queues = "myDirectQueue")
    public void saveFlow(String orderNum, Channel channel, Message message){
        Order order= orderService.getOrderByOrderNum(orderNum);
        //修改优惠券
        if (order.getCustomerAndCouponId()!=null){
            CustomerAndCoupon customerAndCoupon=customerAndCouponService.getById(order.getCustomerAndCouponId());
            customerAndCoupon.setCustomerAndCouponStatus(1);
            customerAndCouponService.updateById(customerAndCoupon);
        }
        //1.添加流水，2.修改订单,3.解锁座位
        Flow flow =  new Flow();
        flow.setFlowNum(UUID.randomUUID().toString().replace("-",""));
        flow.setOrderId(order.getOrderId());
        flow.setOrderNum(orderNum);
        flow.setCustomerId(order.getCustomerId());
        flow.setFlowPrice(order.getOrderAdjustedPrice());
        flow.setFlowStatus(1);
        flow.setFlowCreateTime(LocalDateTime.now());
        try {
            order.setOrderStatus(1);
            flowService.save(flow);
            orderService.updateOrder(order);
            String[] seats= order.getOrderSeatNum().split(",");
            for (String s:seats) {
                redisTemplate.delete("seat_"+order.getScheduleId()+"_"+s);
            }
            System.out.println("准备开始 ack ...............");
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (IOException e) {
            e.printStackTrace();
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }

    }


}
